/*****************************************************************************
 * $LastChangedDate: 2011-04-23 21:07:07 -0400 (Sat, 23 Apr 2011) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Test of basic types (gfx).
 *//*
 * LEGAL:   COPYRIGHT (C) 2005 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#define COMPILE_VERTEX_TEST 0  // OSG Vec3 differs from Palomino V2 Vector3 (no .x/.y/.z members)
#define TESTING 1
#include "test.hh"
#include "base/module.hh"
using namespace base;
#include "math/module.hh"
using namespace math;
#include "gfx/module.hh"
#include "gfx/graphics.hh"
using namespace gfx;

#if COMPILE_VERTEX_TEST
/*****************************************************************************
 * Test Vertex* class.
 *****************************************************************************/
bool
TestVertex( void )
{
    CERROR << "============================================\n";
    CERROR << "Testing Vertex* class. \n";
    CERROR << "============================================\n";

    // Test operator+()
 {
    WorldVertex v1, v2;
    v1.x = 10.0;
    v1.y = 20.0;
    v1.z = 30.0;
    v2.x = 1.0;
    v2.y = 2.0;
    v2.z = 3.0;
    v1 = v1 + v2;
    if (    int(v1.x) != 11 || int(v1.y) != 22 || int(v1.z) != 33
         || int(v2.x) != 1  || int(v2.y) != 2  || int(v2.z) != 3)
        Fail();
 }

    // Test operator+=()
 {
    WorldVertex v1, v2;
    v1.x = 10.0;
    v1.y = 20.0;
    v1.z = 30.0;
    v2.x = 1.0;
    v2.y = 2.0;
    v2.z = 3.0;
    v1 += v2;
    if (    int(v1.x) != 11 || int(v1.y) != 22 || int(v1.z) != 33
         || int(v2.x) != 1  || int(v2.y) != 2  || int(v2.z) != 3)
        Fail();
 }

    // Test operator-()
 {
    WorldVertex v1, v2;
    v1.x = 10.0;
    v1.y = 20.0;
    v1.z = 30.0;
    v2.x = 1.0;
    v2.y = 2.0;
    v2.z = 3.0;

    v1 = v1 - v2;
    if (    int(v1.x) != 10-1  || int(v1.y) != 20-2 || int(v1.z) != 30-3
         || int(v2.x) != 1  || int(v2.y) != 2  || int(v2.z) != 3)
        Fail();
 }

    // Test operator-=()
 {
    WorldVertex v1, v2;
    v1.x = 10.0;
    v1.y = 20.0;
    v1.z = 30.0;
    v2.x = 1.0;
    v2.y = 2.0;
    v2.z = 3.0;

    v1 -= v2;
    if (    int(v1.x) != 10-1  || int(v1.y) != 20-2 || int(v1.z) != 30-3
         || int(v2.x) != 1  || int(v2.y) != 2  || int(v2.z) != 3)
        Fail();
 }

    // Test operator*()
 {
    WorldVertex v1, v2;
    v1.x = 10.0;
    v1.y = 20.0;
    v1.z = 30.0;
    v2.x = 1.0;
    v2.y = 2.0;
    v2.z = 3.0;
    v1 = v1 * v2;
    if (    int(v1.x) != 10*1  || int(v1.y) != 20*2 || int(v1.z) != 30*3
         || int(v2.x) != 1  || int(v2.y) != 2  || int(v2.z) != 3)
        Fail();
 }

    // Test operator*=()
 {
    WorldVertex v1, v2;
    v1.x = 10.0;
    v1.y = 20.0;
    v1.z = 30.0;
    v2.x = 1.0;
    v2.y = 2.0;
    v2.z = 3.0;
    v1 *= v2;
    if (    int(v1.x) != 10*1  || int(v1.y) != 20*2 || int(v1.z) != 30*3
         || int(v2.x) != 1  || int(v2.y) != 2  || int(v2.z) != 3)
        Fail();
 }

    // Test that copy ctors of Vector3 derivatives,
    // whether provided by C++ compiler or explicitly written,
    // by allocating a large STL container to induce copying.
 {
    const LocalVertex lv( 123.0, 456.0, 789.0 );
    LocalVertexs localVertexs( 1 );
    localVertexs[0] = lv;
    long p1 = long(&localVertexs[0]);
    int* junk = new int[MILLION];    // this allocation is meant to be in the way
    localVertexs.resize(MILLION);  // so that resize() would reallocate the same segment
    localVertexs[MILLION-1] = LocalVertex(0,0,0);
    if ( localVertexs[0].x != lv.x
      || localVertexs[0].y != lv.y
      || localVertexs[0].z != lv.z )
    {
        Fail();
    }
    long p2 = long(&localVertexs[0]);
    if ( p1 == p2 )
    {
        CERROR << "ERROR: Why wasn't localVertexs[0] copied for resize()?" << std::endl;
        Fail();
    }
    delete[] junk;
 }

    return true;
}
#endif // COMPILE_VERTEX_TEST

/*****************************************************************************
 * Test Rect.
 *****************************************************************************/
bool
TestRect( void )
{
    CERROR << "============================================\n";
    CERROR << "Testing Rect class. \n";
    CERROR << "============================================\n";

    // The Rect class, for speed, assumes (x1,y1) is less than (x2,y2).

 {
    CERROR << "----------- testing IfInside() --------- \n";

    Rect<int> rect( 10, 20, 500, 600 );

    if ( ! rect.IfInside( 10, 20 ) ) Fail();    // barely inside
    if ( ! rect.IfInside( 500, 600 ) ) Fail();  // barely inside

    if ( ! rect.IfInside( 11, 21 ) ) Fail();
    if ( ! rect.IfInside( 499, 599 ) ) Fail();

    if ( rect.IfInside( 0, 0 ) ) Fail();        // not inside
    if ( rect.IfInside( -10, -20 ) ) Fail();    // not inside
    if ( rect.IfInside( -510, -620 ) ) Fail();  // not inside
    if ( rect.IfInside( 1000, 1000 ) ) Fail();  // not inside
    if ( rect.IfInside( 10, 601 ) ) Fail();     // not inside

    CERROR << "ok\n";
 }

 {
    CERROR << "----------- testing IfOutside() --------- \n";

    Rect<int> rect( 200, 200, 300, 300 );

    // Entirely outside
    if ( ! rect.IfOutside( Rect<int>( 50,50,60,60 ) ) ) Fail();
    if ( ! rect.IfOutside( Rect<int>( -50,-50,-40,-40 ) ) ) Fail();
    if ( ! rect.IfOutside( Rect<int>( 1000,1000,1100,1100 ) ) ) Fail();

    // Overlaps.  IfOutside() should return false.
    if ( rect.IfOutside( Rect<int>(199, 199, 200, 200) ) ) Fail();
    if ( rect.IfOutside( Rect<int>(1,1, 5000,5000) ) ) Fail();
    if ( rect.IfOutside( Rect<int>(-500,-500, 5000,5000) ) ) Fail();

    // Inside.  IfOutside() should return false.
    if ( rect.IfOutside( Rect<int>(200,200,201,201) ) ) Fail();
    if ( rect.IfOutside( Rect<int>(201,201,299,299) ) ) Fail();

    // Catch this stupid typo:
    //   return     rect.x1 > x2    // if to the right
    //           || rect.x2 < y1    // if to the left
    //                        ^^ oops
    //           || rect.y1 > y2    // if below
    //           || rect.y2 < y1;   // if above
    Rect<int> rect2( 100,400, 200,500 );
    if ( rect2.IfOutside( Rect<int>(101,401, 199,499) ) ) Fail();

    CERROR << "ok\n";
 }

 {
    CERROR << "----------- testing Grow() --------- \n";

    Rect<int> rect( 600, 601, 700, 701 );

    rect.Grow( 500, 501 );
    if (    rect.x1 != 500
         || rect.y1 != 501
         || rect.x2 != 700
         || rect.y2 != 701 ) Fail();

    rect.Grow( 1010, 1011 );
    if (    rect.x1 != 500
         || rect.y1 != 501
         || rect.x2 != 1010
         || rect.y2 != 1011 ) Fail();

    CERROR << "ok\n";
 }

 {
    CERROR << "----------- testing IfOverlaps() --------- \n";

    Rect<int> rect1( 50, 50, 150, 150 );
    Rect<int> rect2( 75, 75, 100, 100 );
    if ( not rect1.IfOverlaps(rect2) ) return Fail();
    if ( not rect2.IfOverlaps(rect1) ) return Fail();
 }

 {
    CERROR << "----------- testing width,height --------- \n";

    Rect<int> rect( 100, 50, 500, 600 );
    if ( rect.GetWidth() != 500-100 ) return Fail();
    if ( rect.GetHeight() != 600-50 ) return Fail();
 }

    return true;
}

/*****************************************************************************
 * Run all tests per conditional-compiling.
 *****************************************************************************/
bool
RunAllTests( void )
{
    return TestRect()
#if COMPILE_VERTEX_TEST
       and TestVertex()
#endif
    ;  // semicolon
}

/*****************************************************************************
 * main.
 *****************************************************************************/
int main( int argc, char** argv )
{
    RUN_TEST( "graphics basic types", TEST_ERROR_MODE_ABORT,
              RunAllTests() )
}
